package com.yuxl.common.auth.config;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yuxl.common.core.domain.R;
import com.yuxl.common.core.domain.auth.JwtUser;
import com.yuxl.common.auth.utils.JwtUtil;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.data.redis.core.ReactiveRedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;
import java.util.Collections;
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
import org.springframework.stereotype.Component;

@Component
public class JwtAuthenticationFilter implements WebFilter {
    @Resource
    private ReactiveRedisTemplate<String,String> reactiveRedisTemplate;

    @Resource
    private JwtParameter jwtParameter;
    @Resource
    private JwtUtil jwtUtil;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        String token = jwtUtil.getToken(exchange);
        if (StringUtils.isNotEmpty(token)) {
            if (jwtUtil.validateToken(token)) {
                return reactiveRedisTemplate.hasKey(jwtParameter.getTokenKey() + token)
                        .flatMap(isWhitelisted -> {
                            if (isWhitelisted) {
                                JwtUser jwt = jwtUtil.getJwtFromToken(token);
                                Authentication auth = new UsernamePasswordAuthenticationToken(jwt.username(), token, Collections.emptyList());
                                return chain.filter(exchange).contextWrite(ReactiveSecurityContextHolder.withAuthentication(auth));
                            }else{
                                return chain.filter(exchange);
                            }
                        });
            }
        }
        return chain.filter(exchange);
    }


}